﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Fly.Common.Extensions
{
    /// <summary>
    /// Dictionary 扩展
    /// </summary>
    public static class DictionaryExtensions
    {
        #region 获取

        /// <summary>
        /// 尝试获取指定键名的键值,如果该键不存在则返回该键值的默认值
        /// </summary>
        /// <typeparam name="TKey">键名的类型</typeparam>
        /// <typeparam name="TValue">键值的类型</typeparam>
        /// <param name="dictionary">需要操作的字典</param>
        /// <param name="key">键名</param>
        /// <returns></returns>
        public static TValue GetValueOfDefault<TKey, TValue>(this IDictionary<TKey, TValue> dictionary, TKey key)
        {
            TValue value;
            dictionary.TryGetValue(key, out value);
            return value;
        }

        #endregion

        #region 添加或更新
        /// <summary>
        /// 如果当前字典中存在指定的键值，则更新，否则则添加
        /// </summary>
        /// <typeparam name="TK">键名的类型</typeparam>
        /// <typeparam name="TV">键值的类型</typeparam>
        /// <param name="dictionary">需要操作的字典</param>
        /// <param name="key">键名</param>
        /// <param name="value">键值</param>
        public static void AddOrUpdate<TK, TV>(this Dictionary<TK, TV> dictionary, TK key, TV value)
        {
            lock (dictionary)
            {
                if (dictionary.ContainsKey(key))
                {
                    dictionary.Remove(key);
                }
                dictionary.Add(key, value);
            }
        } 
        #endregion

        #region 获取或更新
        /// <summary>
        /// 获取指定键名的值，如果不存在则添加
        /// </summary>
        /// <typeparam name="TK">键名的类型</typeparam>
        /// <typeparam name="TV">键值的类型</typeparam>
        /// <param name="dictionary">需要操作的字典</param>
        /// <param name="key">键名</param>
        /// <param name="value">键值</param>
        /// <returns></returns>
        public static TV GetOrAdd<TK, TV>(this Dictionary<TK, TV> dictionary, TK key, TV value)
        {
            lock (dictionary)
            {
                if (dictionary.ContainsKey(key))
                {
                    TV tv;
                    if (dictionary.TryGetValue(key, out tv))
                    {
                        return tv;
                    }
                }
                dictionary.Add(key, value);
                return value;
            }
        } 
        #endregion

        #region 批量导入
        /// <summary>
        /// 将两个字典合并为一个字典
        /// </summary>
        /// <typeparam name="TDictionary">源字典</typeparam>
        /// <typeparam name="TKey">键名类型</typeparam>
        /// <typeparam name="TValue">键值类型</typeparam>
        /// <param name="source">源字典</param>
        /// <param name="copy">目标字典</param>
        /// <returns></returns>
        public static TDictionary CopyFrom<TDictionary, TKey, TValue>(this TDictionary source, IDictionary<TKey, TValue> copy) where TDictionary : IDictionary<TKey, TValue>
        {
            foreach (var pair in copy)
            {
                source.Add(pair.Key, pair.Value);
            }

            return source;
        }
        /// <summary>
        /// 将两个字典合并为一个字典
        /// </summary>
        /// <typeparam name="TDictionary">字典类型</typeparam>
        /// <typeparam name="TKey">键名类型</typeparam>
        /// <typeparam name="TValue">键值类型</typeparam>
        /// <param name="source">源字典</param>
        /// <param name="copy">目标字典</param>
        /// <param name="keys">键名列表</param>
        /// <returns></returns>
        public static TDictionary CopyFrom<TDictionary, TKey, TValue>(this TDictionary source, IDictionary<TKey, TValue> copy, IEnumerable<TKey> keys) where TDictionary : IDictionary<TKey, TValue>
        {
            foreach (var key in keys)
            {
                source.Add(key, copy[key]);
            }

            return source;
        } 
        #endregion

        #region 批量删除
        /// <summary>
        /// 从字典中移除键名列表中所有键值
        /// </summary>
        /// <typeparam name="TDictionary">字典类型</typeparam>
        /// <typeparam name="TKey">键名类型</typeparam>
        /// <typeparam name="TValue">键值类型</typeparam>
        /// <param name="source">源字典</param>
        /// <param name="keys">键名列表</param>
        /// <returns></returns>
        public static TDictionary RemoveKeys<TDictionary, TKey, TValue>(this TDictionary source, IEnumerable<TKey> keys) where TDictionary : IDictionary<TKey, TValue>
        {
            foreach (var key in keys)
            {
                if (key != null && source.ContainsKey(key))
                {
                    source.Remove(key);
                }
            }

            return source;
        }
        /// <summary>
        /// 从字典中移除键名列表中所有键值
        /// </summary>
        /// <typeparam name="TKey">键名类型</typeparam>
        /// <typeparam name="TValue">键值类型</typeparam>
        /// <param name="source">源字典</param>
        /// <param name="keys">键名列表</param>
        /// <returns></returns>
        public static IDictionary<TKey, TValue> RemoveKeys<TKey, TValue>(this IDictionary<TKey, TValue> source, IEnumerable<TKey> keys)
        {
            foreach (var key in keys)
            {
                source.Remove(key);
            }

            return source;
        } 
        #endregion
    }
}
